/**
 * 文件选择选项接口
 */
interface FileSelectOptions {
  accept?: string; // 接受的文件类型，例如：'image/*'、'.pdf,.doc'、'video/*'
  multiple?: boolean; // 是否允许多选
  capture?: string; // 捕获设备，例如：'camera'、'microphone'
}

/**
 * 文件选择结果接口
 */
interface FileSelectResult {
  files: File[]; // 选择的文件列表
  input: HTMLInputElement; // 创建的 input 元素（可用于清理）
}

/**
 * 使用纯 TypeScript 实现文件选择功能
 * @param options 文件选择选项
 * @returns 包含文件列表和 input 元素的 Promise
 */
export function selectFile(options: FileSelectOptions = {}): Promise<FileSelectResult> {
  return new Promise((resolve, reject) => {
    // 创建 input 元素
    const input = document.createElement('input');
    input.type = 'file';

    // 设置选项
    if (options.accept) {
      input.accept = options.accept;
    }

    if (options.multiple) {
      input.multiple = options.multiple;
    }

    if (options.capture) {
      input.capture = options.capture;
    }

    // 隐藏 input 元素
    input.style.display = 'none';

    // 添加 change 事件监听器
    input.addEventListener('change', () => {
      const files = input.files ? Array.from(input.files) : [];

      if (files.length > 0) {
        resolve({
          files,
          input
        });
      } else {
        reject(new Error('没有选择文件'));
      }

      // 清理 DOM
      if (document.body.contains(input)) {
        document.body.removeChild(input);
      }
    });

    // 添加取消事件监听器（当用户关闭文件选择对话框时）
    const handleWindowFocus = () => {
      setTimeout(() => {
        if (!input.files || input.files.length === 0) {
          reject(new Error('用户取消了文件选择'));

          // 清理 DOM
          if (document.body.contains(input)) {
            document.body.removeChild(input);
          }

          window.removeEventListener('focus', handleWindowFocus);
        }
      }, 1000);
    };

    window.addEventListener('focus', handleWindowFocus);

    // 将 input 添加到 DOM 并触发点击
    document.body.appendChild(input);
    input.click();
  });
}

/**
 * 高级文件选择器，支持更多选项
 */
export class FileSelector {
  /**
   * 选择单个文件
   * @param accept 接受的文件类型
   * @returns 选择的文件
   */
  static async selectSingleFile(accept?: string): Promise<File> {
    const result = await selectFile({ accept, multiple: false });
    return result.files[0];
  }

  /**
   * 选择多个文件
   * @param accept 接受的文件类型
   * @returns 选择的文件列表
   */
  static async selectMultipleFiles(accept?: string): Promise<File[]> {
    const result = await selectFile({ accept, multiple: true });
    return result.files;
  }

  /**
   * 选择图片文件
   * @param multiple 是否允许多选
   * @returns 选择的图片文件
   */
  static async selectImage(multiple: boolean = false): Promise<File[]> {
    return this.selectFiles('image/*', multiple);
  }

  /**
   * 选择视频文件
   * @param multiple 是否允许多选
   * @returns 选择的视频文件
   */
  static async selectVideo(multiple: boolean = false): Promise<File[]> {
    return this.selectFiles('video/*', multiple);
  }

  /**
   * 选择音频文件
   * @param multiple 是否允许多选
   * @returns 选择的音频文件
   */
  static async selectAudio(multiple: boolean = false): Promise<File[]> {
    return this.selectFiles('audio/*', multiple);
  }

  /**
   * 选择文档文件
   * @param multiple 是否允许多选
   * @returns 选择的文档文件
   */
  static async selectDocument(multiple: boolean = false): Promise<File[]> {
    const accept = '.pdf,.doc,.docx,.txt,.rtf,.odt';
    return this.selectFiles(accept, multiple);
  }

  /**
   * 通用文件选择方法
   * @param accept 接受的文件类型
   * @param multiple 是否允许多选
   * @returns 选择的文件
   */
  private static async selectFiles(accept: string, multiple: boolean): Promise<File[]> {
    const result = await selectFile({ accept, multiple });
    return result.files;
  }
}

/**
 * 文件信息工具类
 */
export class FileUtils {
  /**
   * 获取文件大小（带单位）
   * @param file 文件对象
   * @returns 格式化的文件大小
   */
  static getFileSize(file: File): string {
    const bytes = file.size;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];

    if (bytes === 0) return '0 Bytes';

    const i = Math.floor(Math.log(bytes) / Math.log(1024));
    return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
  }

  /**
   * 获取文件扩展名
   * @param file 文件对象
   * @returns 文件扩展名
   */
  static getFileExtension(file: File): string {
    return file.name.split('.').pop()?.toLowerCase() || '';
  }

  /**
   * 检查文件类型是否匹配
   * @param file 文件对象
   * @param mimeType MIME 类型
   * @returns 是否匹配
   */
  static isFileType(file: File, mimeType: string): boolean {
    return file.type.startsWith(mimeType.replace('/*', ''));
  }

  /**
   * 读取文件为 Data URL
   * @param file 文件对象
   * @returns Data URL
   */
  static readAsDataURL(file: File): Promise<string> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result as string);
      reader.onerror = () => reject(reader.error);
      reader.readAsDataURL(file);
    });
  }

  /**
   * 读取文件为文本
   * @param file 文件对象
   * @returns 文件文本内容
   */
  static readAsText(file: File): Promise<string> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result as string);
      reader.onerror = () => reject(reader.error);
      reader.readAsText(file);
    });
  }
}

// // 使用示例
// export async function demonstrateFileSelection() {
//   try {
//     // 示例 1: 选择单个图片
//     const imageFile = await FileSelector.selectSingleFile('image/*');
//     console.log('选择的图片:', imageFile.name);
//     console.log('文件大小:', FileUtils.getFileSize(imageFile));

//     // 示例 2: 选择多个文档
//     const docFiles = await FileSelector.selectDocument(true);
//     console.log(`选择了 ${docFiles.length} 个文档文件`);

//     // 示例 3: 使用基础方法选择文件
//     const result = await selectFile({
//       accept: '.pdf,.doc,.docx',
//       multiple: true
//     });
//     console.log('选择的文件:', result.files.map(f => f.name));

//     // 示例 4: 读取文件内容
//     const textContent = await FileUtils.readAsText(imageFile);
//     console.log('文件内容预览:', textContent.substring(0, 100));

//   } catch (error) {
//     if (error instanceof Error) {
//       console.error('文件选择错误:', error.message);
//     }
//   }
// }

// 导出主要功能
export default selectFile;
